#include "grid.h"
#include <algorithm>
#include <cmath>


Grid::Grid(LPDIRECT3DDEVICE9 device) : m_device(device)
, m_vb(NULL)
, m_ib(NULL)
, m_cur_frame(NULL)
, m_indices(NULL)
, index_num(0)
, vertex_num(0)
{
	Init();
}

Grid::~Grid()
{
	Release();
}

void Grid::Init()
{
	vertex_num = HEIGHT * WIDTH + 6;
	m_cur_frame = new CUSTOMVERTEX[vertex_num];
	SetupVertices();

	index_num = ( ( HEIGHT - 1 ) * WIDTH + ( WIDTH - 1 ) * HEIGHT ) * 2 + 6;
	m_indices = new unsigned short[index_num];
	SetupIndices();
}

void Grid::SetupVertices()
{
	int i = 0, j = 0;
	int w = WIDTH/2, h = HEIGHT/2;
	for( i = 0; i < HEIGHT; ++i)
	{
		for( j = 0; j < WIDTH; ++j)
		{
			m_cur_frame[ i * WIDTH + j ].x = (j - w) * GRID_SIZE;
			m_cur_frame[ i * WIDTH + j ].y = (i - h) * GRID_SIZE;
			m_cur_frame[ i * WIDTH + j ].z = INIT_VERTICAL_LEVEL;
			m_cur_frame[ i * WIDTH + j ].color = 0xFFFFFFF;
		}
	}

	m_cur_frame[WIDTH * HEIGHT + 0].x = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 0].y = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 0].z = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 0].color = 0xFFFF0000;

	m_cur_frame[WIDTH * HEIGHT + 1].x = 10.0f;
	m_cur_frame[WIDTH * HEIGHT + 1].y = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 1].z = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 1].color = 0xFFFF0000;

	m_cur_frame[WIDTH * HEIGHT + 2].x = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 2].y = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 2].z = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 2].color = 0xFF00FF00;

	m_cur_frame[WIDTH * HEIGHT + 3].x = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 3].y = 10.0f;
	m_cur_frame[WIDTH * HEIGHT + 3].z = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 3].color = 0xFF00FF00;

	m_cur_frame[WIDTH * HEIGHT + 4].x = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 4].y = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 4].z = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 4].color = 0xFF0000FF;

	m_cur_frame[WIDTH * HEIGHT + 5].x = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 5].y = 0.0f;
	m_cur_frame[WIDTH * HEIGHT + 5].z = 10.0f;
	m_cur_frame[WIDTH * HEIGHT + 5].color = 0xFF0000FF;

	if ( m_vb )
	{
		m_vb->Release();
	}

	size_t siz = sizeof(CUSTOMVERTEX) * vertex_num;

    m_device->CreateVertexBuffer( siz, 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_vb, NULL );

    void *vertices;
	m_vb->Lock( 0, siz, ( void** )&vertices, 0 );
    memcpy( vertices, m_cur_frame, siz );
    m_vb->Unlock();
}

void Grid::SetupIndices()
{
	short i = 0, j = 0;
	int index = 0;

	for( i = 0; i < HEIGHT; ++i)
	{
		for( j = 0; j < WIDTH - 1; ++j)
		{
			m_indices[ index + 0 ] = i * WIDTH + j;
			m_indices[ index + 1 ] = i * WIDTH + j + 1;
			index += 2;
		}
	}
	
	for( i = 0; i < HEIGHT - 1; ++i)
	{
		for( j = 0; j < WIDTH; ++j)
		{
			m_indices[ index + 0 ] = i * WIDTH + j;
			m_indices[ index + 1 ] = ( i + 1 ) * WIDTH + j;
			index += 2;
		}
	}

	for( i = 0; i < 6; ++i)
	{
		m_indices[index + i] = WIDTH * HEIGHT + i;
	}

	if ( m_ib )
	{
		m_ib->Release();
	}
	
	m_device->CreateIndexBuffer(sizeof(unsigned short) * index_num, 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_ib, NULL);

    void *indices;
    m_ib->Lock(0, sizeof(unsigned short) * index_num, (void**)&indices, 0);
    memcpy(indices, m_indices, sizeof(unsigned short) * index_num);
	m_ib->Unlock();
}

//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
void Grid::Release()
{
    if( m_vb != NULL )
	{
        m_vb->Release();
		m_vb = NULL;
	}

	if ( m_ib )
	{
		m_ib->Release();
		m_ib = NULL;
	}

	delete []m_cur_frame;
	m_cur_frame = NULL;

	delete []m_indices;
	m_indices = NULL;
}

//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
void Grid::Render()
{
    // Render the vertex buffer contents
    m_device->SetStreamSource( 0, m_vb, 0, sizeof( CUSTOMVERTEX ) );
    m_device->SetFVF( D3DFVF_CUSTOMVERTEX );
	m_device->SetIndices( m_ib );
	//release texture
	m_device->SetTexture(0, NULL);
    m_device->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vertex_num, 0, index_num / 2);
}
